View Javadoc

1   // InflaterDynHeader.java, created Mon Jul  8  4:06:18 2002 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.ClassLib.Common.java.util.zip;
5   
6   import java.util.zip.DataFormatException;
7   
8   /***
9    * InflaterDynHeader
10   *
11   * @author  John Whaley <jwhaley@alum.mit.edu>
12   * @version $Id: InflaterDynHeader.java 1451 2004-03-09 06:27:08Z jwhaley $
13   */
14  class InflaterDynHeader {
15  
16    private static final int LNUM   = 0;
17    private static final int DNUM   = 1;
18    private static final int BLNUM  = 2;
19    private static final int BLLENS = 3;
20    private static final int LENS   = 4;
21    private static final int REPS   = 5;
22  
23    private static final int repMin[]  = { 3, 3, 11 };
24    private static final int repBits[] = { 2, 3,  7 };
25  
26    
27    private byte[] blLens;
28    private byte[] litdistLens;
29  
30    private InflaterHuffmanTree blTree;
31    
32    private int mode;
33    private int lnum, dnum, blnum, num;
34    private int repSymbol;
35    private byte lastLen;
36    private int ptr;
37  
38    private static final int[] BL_ORDER =
39    { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
40    
41    public InflaterDynHeader()
42    {
43    }
44    
45    public boolean decode(StreamManipulator input) throws DataFormatException
46    {
47    decode_loop:
48      for (;;)
49        {
50          switch (mode)
51            {
52            case LNUM:
53              lnum = input.peekBits(5);
54              if (lnum < 0)
55                return false;
56              lnum += 257;
57              input.dropBits(5);
58  //          System.err.println("LNUM: "+lnum);
59              mode = DNUM;
60              /* fall through */
61            case DNUM:
62              dnum = input.peekBits(5);
63              if (dnum < 0)
64                return false;
65              dnum++;
66              input.dropBits(5);
67  //          System.err.println("DNUM: "+dnum);
68              num = lnum+dnum;
69              litdistLens = new byte[num];
70              mode = BLNUM;
71              /* fall through */
72            case BLNUM:
73              blnum = input.peekBits(4);
74              if (blnum < 0)
75                return false;
76              blnum += 4;
77              input.dropBits(4);
78              blLens = new byte[19];
79              ptr = 0;
80  //          System.err.println("BLNUM: "+blnum);
81              mode = BLLENS;
82              /* fall through */
83            case BLLENS:
84              while (ptr < blnum)
85                {
86                  int len = input.peekBits(3);
87                  if (len < 0)
88                    return false;
89                  input.dropBits(3);
90  //              System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
91                  blLens[BL_ORDER[ptr]] = (byte) len;
92                  ptr++;
93                }
94              blTree = new InflaterHuffmanTree(blLens);
95              blLens = null;
96              ptr = 0;
97              mode = LENS;
98              /* fall through */
99            case LENS:
100             {
101               int symbol;
102               while (((symbol = blTree.getSymbol(input)) & ~15) == 0)
103                 {
104                   /* Normal case: symbol in [0..15] */
105 
106 //                System.err.println("litdistLens["+ptr+"]: "+symbol);
107                   litdistLens[ptr++] = lastLen = (byte) symbol;
108 
109                   if (ptr == num)
110                     {
111                       /* Finished */
112                       return true;
113                     }
114                 }
115               
116               /* need more input ? */
117               if (symbol < 0)
118                 return false;
119 
120               /* otherwise repeat code */
121               if (symbol >= 17)
122                 {
123                   /* repeat zero */
124 //                System.err.println("repeating zero");
125                   lastLen = 0;
126                 }
127               else
128                 {
129                   if (ptr == 0)
130                     throw new DataFormatException();
131                 }
132               repSymbol = symbol-16;
133               mode = REPS;
134             }
135             /* fall through */
136 
137           case REPS:
138             {
139               int bits = repBits[repSymbol];
140               int count = input.peekBits(bits);
141               if (count < 0)
142                 return false;
143               input.dropBits(bits);
144               count += repMin[repSymbol];
145 //            System.err.println("litdistLens repeated: "+count);
146 
147               if (ptr + count > num)
148                 throw new DataFormatException();
149               while (count-- > 0)
150                 litdistLens[ptr++] = lastLen;
151 
152               if (ptr == num)
153                 {
154                   /* Finished */
155                   return true;
156                 }
157             }
158             mode = LENS;
159             continue decode_loop;
160           }
161       }
162   }
163 
164   public InflaterHuffmanTree buildLitLenTree() throws DataFormatException
165   {
166     byte[] litlenLens = new byte[lnum];
167     System.arraycopy(litdistLens, 0, litlenLens, 0, lnum);
168     return new InflaterHuffmanTree(litlenLens);
169   }
170 
171   public InflaterHuffmanTree buildDistTree() throws DataFormatException
172   {
173     byte[] distLens = new byte[dnum];
174     System.arraycopy(litdistLens, lnum, distLens, 0, dnum);
175     return new InflaterHuffmanTree(distLens);
176   }
177 }